package com.gitee.wsl.android.net

import android.annotation.SuppressLint
import android.content.ComponentName
import android.content.Context
import android.content.Context.BIND_AUTO_CREATE
import android.content.Intent
import android.content.ServiceConnection
import android.os.Bundle
import android.os.Handler
import android.os.IBinder
import android.os.Message
import java.util.concurrent.CopyOnWriteArrayList

class ConnectManager<REQUEST: BaseRequest,RESPONSE: BaseResponse> {
    private val requestList: MutableList<REQUEST?> =
        CopyOnWriteArrayList<REQUEST?>() //注意线程安全，ArrayList出问题

    @SuppressLint("HandlerLeak")
    private val uiHandler: Handler = object : Handler() {
        override fun handleMessage(msg: Message) {
            when (msg.what) {
                0 -> handleError(msg.arg1)
                1 -> {
                    val response: RESPONSE = msg.data.getParcelable("response")!!
                    handleResponse(response)
                }

                -1 -> {
                    handleTimeout()
                    this.sendEmptyMessageDelayed(-1, 100)
                }

                else -> {}
            }
        }
    }
    private var mBinder: ConnectService<REQUEST, RESPONSE>.ConnectBinder? = null
    private val connection: ServiceConnection = object : ServiceConnection {
        override fun onServiceConnected(componentName: ComponentName, iBinder: IBinder) {
            mBinder = iBinder as ConnectService<REQUEST, RESPONSE>.ConnectBinder
            //回调处理发送失败
            mBinder!!.service.setOnPostMessageListener(object : OnPostMessageListener<RESPONSE> {
                override fun onPostError(typeId: Int) {
                    sendErrorToUiThread(typeId)
                }

                override fun onPostResponse(response: RESPONSE) {
                    sendResponseToUiThread(response)
                }
            })
        }

        override fun onServiceDisconnected(componentName: ComponentName) {}
    }

    fun setUpSocketConfigure(data: Bundle) {
        mBinder!!.setUpSocketConfigure(data)
        uiHandler.sendEmptyMessage(-1)
    }

    fun sendMessage(request: REQUEST) {
        requestList.add(request)
        //TODO 解决mBinder为空
        if (request.isSendOut && mBinder != null) {
            mBinder!!.sendMessage(request)
        }
    }

    fun bindConnectService(context: Context) {
        val intent = Intent(context, ConnectService::class.java)
        context.bindService(intent, connection, BIND_AUTO_CREATE)
    }

    fun unbindConnectService(context: Context) {
        context.unbindService(connection)
    }

    private fun sendErrorToUiThread(typeId: Int) {
        val message: Message = uiHandler.obtainMessage(-1, typeId, 0)
        uiHandler.sendMessage(message)
    }

    private fun sendResponseToUiThread(response: RESPONSE) {
        val message: Message = uiHandler.obtainMessage(1)
        val bundle = Bundle()
        bundle.putParcelable("response", response)
        message.data = bundle
        uiHandler.sendMessage(message)
    }

    private fun handleError(typeId: Int) {
        for (request in requestList) {
            if (request == null) {
                requestList.remove(null)
            } else if (request.requestMsgType == typeId) {
                request.callback!!.onError(typeId)
                requestList.remove(request)
            }
        }
    }

    /* --处理说明--
    一对零：不求回复，直接移除（checkTimeout）

    一对一：一般模式，直接结束
    一对多：定位报值，多条接受

    零/一对无限：wantNumb = -1,特别处理
    */
    private fun handleResponse(response: RESPONSE) {
        for (request in requestList) {
            if (request == null) {
                requestList.remove(null)
            } else if (request.responseMsgType == response.responseMsgType) {
                if (!request.isReachWant || request.isWantInfinite) {
                    request.callback!!.onResponse(response)
                    request.addNowNumb()
                    if (request.isReachWant && !request.isWantInfinite) {
                        requestList.remove(request)
                    }
                } else {
                    requestList.remove(request)
                }
            }
        }
    }

    private fun handleTimeout() {
        val nowTime = System.currentTimeMillis()
        for (request in requestList) {
            if (request == null) {
                requestList.remove(null)
            } else if (request.wantNumb == 0) {
                requestList.remove(request)
            } else if (request.isTimeout(nowTime) && !request.isWantInfinite) {
                request.callback!!.onTimeout(request.requestMsgType)
                requestList.remove(request)
            }
        }
    }

    companion object {
       /* @Volatile
        private var mConnectManager: ConnectManager? = null

        //DCL
        val instance: ConnectManager?
            get() {
                if (mConnectManager == null) {
                    synchronized(ConnectManager::class.java) {
                        if (mConnectManager == null) {
                            mConnectManager = ConnectManager()
                        }
                    }
                }
                return mConnectManager
            }*/
    }
}